package com.vshining.cryptoki.jna;

import com.sun.jna.NativeLong;
import com.vshining.cryptoki.jna.pkcs11t.CK_ATTRIBUTE;

import java.io.UnsupportedEncodingException;

import static com.vshining.cryptoki.jna.pkcs11t.CRYPTOKI_TYPE.CK_FALSE;
import static com.vshining.cryptoki.jna.pkcs11t.CRYPTOKI_TYPE.CK_TRUE;
import static com.vshining.cryptoki.jna.pkcs11t.CRYPTOKI_TYPE.PKCS11_CHARSET;

/**
 * @author Shining Wang <shiningwang@vshining.com>
 */
@SuppressWarnings("unused")
public final class ClassConvertor {
    public static byte[] jCharArrayToCKCharArray(char[] charArray) {
        return jStringToCKCharArray(new String(charArray));
    }

    public static byte[] jCharArrayToCKCharArray(char[] charArray,
                                                 int charArrayCount) {
        return jStringToCKCharArray(new String(charArray), charArrayCount);
    }

    public static byte[] jStringToCKCharArray(String charArrayString) {
        return jStringToCKCharArray(charArrayString, 0);
    }

    public static byte[] jStringToCKCharArray(String charArrayString,
                                              int charArrayCount) {
        byte[] origin;
        try {
            origin = charArrayString.getBytes("UTF-8");
            if (charArrayCount < 1) {
                charArrayCount = origin.length;
            }
        } catch (UnsupportedEncodingException e) {
            throw new Error("convert char-arrsy(String) to UTF-8 bytes fail", e);
        }
        // we must output byte[charArrayCount] (blank padded)
        byte[] byteArray = new byte[charArrayCount];
        System.arraycopy(origin, 0, byteArray, 0,
                Math.min(byteArray.length, origin.length));
        return byteArray;
    }

    public static char[] ckCharArrayTojCharArray(byte[] ckCharArray) {
        return ckCharArrayTojString(ckCharArray).toCharArray();
    }

    public static String ckCharArrayTojString(byte[] ckCharArray) {
        try {
            return new String(ckCharArray, PKCS11_CHARSET);
        } catch (UnsupportedEncodingException e) {
            throw new Error("convert char-arrsy(String) to UTF-8 bytes fail", e);
        }
    }

    public static NativeLong jLongToCKULong(long value) {
        return new NativeLong(value);
    }

    public static long ckUlongTojLong(NativeLong value) {
        return Long.valueOf(Integer.toHexString(value.intValue()), 16);
    }

    public static byte jBooleanToCKBBool(boolean value) {
        return value ? CK_TRUE : CK_FALSE;
    }

    public static long[] ckULongArrayToJLongArray(NativeLong[] ckpArray) {
        return ckULongArrayToJLongArray(ckpArray, ckpArray.length);
    }

    public static long[] ckULongArrayToJLongArray(NativeLong[] ckpArray,
                                                  int ckpArrayCount) {
        long[] jpTemp = new long[ckpArrayCount];
        for (int i = 0; i < jpTemp.length; i++) {
            jpTemp[i] = ckUlongTojLong(ckpArray[i]);
        }
        return jpTemp;
    }

    public static CK_ATTRIBUTE[] jAttributeArrayToCKAttributeArray(
            CK_ATTRIBUTE[] jckArray) {
        if (jckArray == null || jckArray.length == 0) {
            return jckArray;
        }
        CK_ATTRIBUTE[] ckpArray = (CK_ATTRIBUTE[]) new CK_ATTRIBUTE()
                .toArray(jckArray.length);
        for (int i = 0; i < jckArray.length; i++) {
            ckpArray[i].type = jckArray[i].type;
            ckpArray[i].pValue = jckArray[i].pValue;
            ckpArray[i].ulValueLen = jckArray[i].ulValueLen;
        }
        return ckpArray;
    }
}
